home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue32 / sweetd / FILEDIRX.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-12-07  |  7.9 KB  |  256 lines

  1. {*********************************************************}
  2. {* FileDirX                                              *}
  3. {* Copyright (c) Julian M Bucknall 1997                  *}
  4. {* All rights reserved.                                  *}
  5. {*********************************************************}
  6. {* Extended directory search routines                    *}
  7. {*********************************************************}
  8.  
  9. {Note: this unit is released as freeware. In other words, you are free
  10.        to use this unit in your own applications, however I retain all
  11.        copyright to the code. JMB}
  12.  
  13. unit FileDirX;
  14.  
  15. interface
  16.  
  17. uses
  18.   {$IFDEF Windows}
  19.   WinTypes, WinProcs,
  20.   {$ELSE}
  21.   Windows,
  22.   {$ENDIF}
  23.   FileRegX,
  24.   SysUtils;
  25.  
  26. type
  27.   TdeType = (                  {types of entries in a directory}
  28.              detFile,          {..file}
  29.              detDirectory,     {..subdirectory}
  30.              detVolumeID);     {..volume ID}
  31.   TdeTypeSet = set of TdeType; {set of directory entries}
  32.  
  33. type
  34.   TdeAttr = (                  {attributes for entries in a directory}
  35.              deaNormal,        {..nothing special, normal}
  36.              deaAltered,       {..it's been altered since last backup}
  37.              deaReadOnly,      {..it's read only}
  38.              deaHidden,        {..it's hidden}
  39.              deaSystem);       {..it's a system entry}
  40.   TdeAttrSet = set of TdeAttr; {set of direntry attributes}
  41.  
  42. const
  43.   c_NormalEntries = [detFile, detDirectory];
  44.     {-handy constant for the normal directory entries}
  45.   c_AllAttrs = [deaNormal, deaAltered, deaReadOnly, deaHidden, deaSystem];
  46.     {-handy constant for all attributes}
  47.  
  48. type
  49.   TdeSearchRec = record
  50.     srName   : string;            {name of directory entry}
  51.     srType   : TdeType;           {type of directory entry}
  52.     srAttrs  : TdeAttrSet;        {attribute set}
  53.     srSize   : longint;           {size in bytes}
  54.     srSizeHi : longint;           {size in bytes, high longint}
  55.     srTime   : longint;           {timestamp MSDOS style}
  56.     {---internal fields---}
  57.     srFindTypes: TdeTypeSet;      {types to find}
  58.     srFindAttrs: TdeAttrSet;      {attributes to match}
  59.     srRegex    : PfrxBinPattern;  {compiled regex}
  60.     {$IFDEF Windows}
  61.     srSR       : TSearchRec;      {search rec}
  62.     {$ENDIF}
  63.     {$IFDEF Win32}
  64.     srHandle   : THandle;         {find handle}
  65.     srSR       : TWin32FindData;  {find data}
  66.     {$ENDIF}
  67.   end;
  68.  
  69. function FindFirstEx(const aPath        : string;
  70.                      const aNamePattern : string;
  71.                            aTypes       : TdeTypeSet;
  72.                            aAttrs       : TdeAttrSet;
  73.                        var aSearchRec   : TdeSearchRec) : integer;
  74. function FindNextEx(var aSearchRec : TdeSearchRec) : integer;
  75. procedure FindCloseEx(var aSearchRec : TdeSearchRec);
  76.  
  77. implementation
  78.  
  79. {===Helper routines==================================================}
  80. function AddStarDotStar(const Path : string) : string;
  81. begin
  82.   if (Path[length(Path)] <> '\') then
  83.     Result := Path + '\*.*'
  84.   else
  85.     Result := Path + '*.*';
  86. end;
  87. {--------}
  88. function ConvertAttr(aOSAttr : integer) : TdeAttrSet;
  89. begin
  90.   Result := [];
  91.   if ((faHidden and aOSAttr) <> 0) then
  92.     Include(Result, deaHidden);
  93.   if ((faSysFile and aOSAttr) <> 0) then
  94.     Include(Result, deaSystem);
  95.   if ((faReadOnly and aOSAttr) <> 0) then
  96.     Include(Result, deaReadOnly);
  97.   if ((faArchive and aOSAttr) <> 0) then
  98.     Include(Result, deaAltered);
  99.   if (Result = []) then
  100.     Result := [deaNormal];
  101. end;
  102. {--------}
  103. function ConvertType(aOSAttr : integer) : TdeType;
  104. begin
  105.   if ((faDirectory and aOSAttr) <> 0) then
  106.     Result := detDirectory
  107.   else if ((faVolumeID and aOSAttr) <> 0) then
  108.     Result := detVolumeID
  109.   else
  110.     Result := detFile;
  111. end;
  112. {--------}
  113. procedure CompleteSearchRec(var SR : TdeSearchRec);
  114. {$IFDEF Windows}
  115. begin
  116.   with SR do begin
  117.     srName := srSR.Name;
  118.     srType := ConvertType(srSR.Attr);
  119.     srAttrs := ConvertAttr(srSR.Attr);
  120.     srSize := srSR.Size;
  121.     srSizeHi := 0;
  122.     srTime := srSR.Time;
  123.   end;
  124. end;
  125. {$ELSE}
  126. type
  127.   LH = packed record L, H : word; end;
  128. var
  129.   LocalFileTime : TFileTime;
  130. begin
  131.   with SR do begin
  132.     srName := srSR.cFileName;
  133.     srType := ConvertType(srSR.dwFileAttributes);
  134.     srAttrs := ConvertAttr(srSR.dwFileAttributes);
  135.     srSize := srSR.nFileSizeLow;
  136.     srSizeHi := srSR.nFileSizeHigh;
  137.     FileTimeToLocalFileTime(srSR.ftLastWriteTime, LocalFileTime);
  138.     FileTimeToDosDateTime(LocalFileTime, LH(srTime).H, LH(srTime).L);
  139.   end;
  140. end;
  141. {$ENDIF}
  142. {====================================================================}
  143.  
  144.  
  145. {===Interfaced routines==============================================}
  146. function FindFirstEx(const aPath        : string;
  147.                      const aNamePattern : string;
  148.                            aTypes       : TdeTypeSet;
  149.                            aAttrs       : TdeAttrSet;
  150.                        var aSearchRec   : TdeSearchRec) : integer;
  151. var
  152.   RegResult : TfrxCompileResult;
  153.   FoundOne  : boolean;
  154. begin
  155.   FillChar(aSearchRec, sizeof(aSearchRec), 0);
  156.   with aSearchRec do begin
  157.     srFindTypes := aTypes;
  158.     srFindAttrs := aAttrs;
  159.     RegResult := FRXCompilePattern(aNamePattern, srRegex);
  160.     if (RegResult <> frxcrSuccess) then begin
  161.       Result := -ord(RegResult);
  162.       Exit;
  163.     end;
  164.     {$IFDEF Windows}
  165.     Result := SysUtils.FindFirst(AddStarDotStar(aPath), faAnyFile, srSR);
  166.     if (Result <> 0) then begin
  167.       FRXFreeBinPattern(srRegex);
  168.     end
  169.     {$ELSE}
  170.     Result := 0;
  171.     srHandle := Windows.FindFirstFile(PChar(AddStarDotStar(aPath)), srSR);
  172.     if (srHandle = INVALID_HANDLE_VALUE) then begin
  173.       FRXFreeBinPattern(srRegex);
  174.       Result := GetLastError;
  175.     end
  176.     {$ENDIF}
  177.     else begin
  178.       FoundOne := false;
  179.       while (Result = 0) and (not FoundOne) do begin
  180.         CompleteSearchRec(aSearchRec);
  181.         if (srType in srFindTypes) and
  182.            ((srFindAttrs * srAttrs) = srAttrs) and
  183.            FRXMatchesPattern(srRegex, srName) then begin
  184.           FoundOne := true;
  185.         end
  186.         else begin
  187.           {$IFDEF Windows}
  188.           Result := SysUtils.FindNext(srSR);
  189.           if (Result <> 0) then
  190.             FRXFreeBinPattern(srRegex);
  191.           {$ELSE}
  192.           if not Windows.FindNextFile(srHandle, srSR) then begin
  193.             CloseHandle(srHandle);
  194.             FRXFreeBinPattern(srRegex);
  195.             Result := GetLastError;
  196.           end;
  197.           {$ENDIF}
  198.         end;
  199.       end;
  200.     end;
  201.   end;
  202. end;
  203. {--------}
  204. function FindNextEx(var aSearchRec : TdeSearchRec) : integer;
  205. var
  206.   FoundOne  : boolean;
  207. begin
  208.   with aSearchRec do begin
  209.     {$IFDEF Windows}
  210.     Result := SysUtils.FindNext(srSR);
  211.     if (Result <> 0) then begin
  212.       {do nothing};
  213.     end
  214.     {$ELSE}
  215.     Result := 0;
  216.     if not Windows.FindNextFile(srHandle, srSR) then begin
  217.       Result := GetLastError;
  218.     end
  219.     {$ENDIF}
  220.     else begin
  221.       FoundOne := false;
  222.       while (Result = 0) and (not FoundOne) do begin
  223.         CompleteSearchRec(aSearchRec);
  224.         if (srType in srFindTypes) and
  225.            ((srFindAttrs * srAttrs) = srAttrs) and
  226.            FRXMatchesPattern(srRegex, srName) then begin
  227.           FoundOne := true;
  228.         end
  229.         else begin
  230.           {$IFDEF Windows}
  231.           Result := SysUtils.FindNext(srSR);
  232.           {$ELSE}
  233.           if not Windows.FindNextFile(srHandle, srSR) then begin
  234.             Result := GetLastError;
  235.           end;
  236.           {$ENDIF}
  237.         end;
  238.       end;
  239.     end;
  240.   end;
  241. end;
  242. {--------}
  243. procedure FindCloseEx(var aSearchRec : TdeSearchRec);
  244. begin
  245.   FRXFreeBinPattern(aSearchRec.srRegex);
  246.   {$IFDEF Win32}
  247.   if (aSearchRec.srHandle <> INVALID_HANDLE_VALUE) then begin
  248.     CloseHandle(aSearchRec.srHandle);
  249.     aSearchRec.srHandle := INVALID_HANDLE_VALUE;
  250.   end;
  251.   {$ENDIF}
  252. end;
  253. {====================================================================}
  254.  
  255. end.
  256.